package com.tbit.uqbike.client.util;

import cn.hutool.core.util.NumberUtil;
import com.tbit.common.constant.DiscountTypeEnum;
import com.tbit.uqbike.client.constant.AdAccountFeeConstant;
import com.tbit.uqbike.client.constant.DisPatchConstant;
import com.tbit.uqbike.client.pojo.AdAccountFee;
import com.tbit.uqbike.client.pojo.CouponUserDto;
import com.tbit.uqbike.client.pojo.Park;
import com.tbit.uqbike.client.pojo.RideLog;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;

/**
 * 费用计算
 *
 * @author Leon
 * 2017年7月18日 上午11:00:22
 */
public class MoneyUtil {
    static HashMap<String, String[]> map = new HashMap();

    static {
//        0.骑行费用(无任何优惠，不包含罚款)
//        1.每日免费骑行（时长减免）
//        2.新用户优惠（时长减免）
//        3.骑行卡（时长减免）
//        4.优惠券（时长减免）
//        5.会员自定义计费规则
//        6.骑行卡（费用减免）
//        7.会员卡折扣（费用减免）
//        8.特殊认证折扣（费用减免）
//        9.优惠券（费用减免）
//        10.调度费
//        11.调度费豁免
//        12.抵扣后骑行费用
        map.put("cyclingMoney", new String[]{
                DiscountTypeEnum.CYCLINGMONEY.getCode()
        });//骑行费用
        map.put("deductionCyclingMoney", new String[]{
                DiscountTypeEnum.DEDUCTIONCYCLINGMONEY.getCode()
        });//抵扣后骑行费用
        map.put("fineMoney", new String[]{
                DiscountTypeEnum.DISPATCHMONEY.getCode()
        });//罚款费用/调度费
        map.put("deductionFineMoney", new String[]{
                DiscountTypeEnum.DISPATCHMONEY.getCode()
        });//抵扣后罚款费用=罚款费用/调度费（仅涉及人工修改抵扣）
        map.put("cardDeductionMoney", new String[]{
                DiscountTypeEnum.VIPRULE.getCode(),
                DiscountTypeEnum.CARDFEE.getCode(),
                DiscountTypeEnum.VIPFEE.getCode(),
                DiscountTypeEnum.CARDTIME.getCode(),
                DiscountTypeEnum.CONPONTIME.getCode(),
                DiscountTypeEnum.CONPONFEE.getCode()
        });//卡券抵扣金额=会员卡抵扣费用+优惠券抵扣费用+骑行卡抵扣费用
        map.put("otherDeductionMoney", new String[]{
                DiscountTypeEnum.DAYTIME.getCode(),
                DiscountTypeEnum.DAYDISTANCE.getCode(),
                DiscountTypeEnum.DAYTIME_AND_DAYDISTANCE.getCode(),
                DiscountTypeEnum.DAYTIME_OR_DAYDISTANCE.getCode(),
                DiscountTypeEnum.NEWUSERTIME.getCode(),
                DiscountTypeEnum.SPECIALFEE.getCode(),
                DiscountTypeEnum.REDUCEMONEY.getCode()
        });//其他抵扣费用=新用户免费骑行、新用户调度费减免、特殊人员折扣抵扣的骑行费用的金额
        map.put("deduciontMoney", new String[]{
                DiscountTypeEnum.CYCLINGMONEY.getCode(),
                DiscountTypeEnum.DISPATCHMONEY.getCode()
        });//订单总费用=骑行费用+罚款费用
        map.put("deductionEndMoney", new String[]{
                DiscountTypeEnum.DISPATCHMONEY.getCode(),
                DiscountTypeEnum.DEDUCTIONCYCLINGMONEY.getCode(),
                "-" + DiscountTypeEnum.REDUCEMONEY.getCode()
        });//抵扣后总费用=抵扣后骑行费用+抵扣后罚款费用+人工修改订单抵扣金额-新用户免调度费
        map.put("vipCard", new String[]{
                DiscountTypeEnum.VIPRULE.getCode(),
                DiscountTypeEnum.VIPFEE.getCode()
        });//会员卡抵扣费用=会员自定义计费规则、会员卡折扣（费用减免）
        map.put("rideCard", new String[]{
                DiscountTypeEnum.CARDFEE.getCode(),
                DiscountTypeEnum.CARDTIME.getCode()
        });//骑行卡抵扣费用=骑行卡（费用减免）
        map.put("couponCard", new String[]{
                DiscountTypeEnum.CONPONFEE.getCode(),
                DiscountTypeEnum.CONPONTIME.getCode()
        });//优惠券抵扣费用
        map.put("giftCardDeductioMoney", new String[]{
                DiscountTypeEnum.GIFTCARDMONEY.getCode()
        });//礼品卡抵扣金额
    }

    public static HashMap<String, Long> calculationFeeDetail(HashMap<String, Double> dataMap) {
        HashMap<String, Long> sumMap = new HashMap();
        map.forEach((key, arr) -> {
            Double cache = 0d;
            for (String s : arr) {
                if (s.startsWith("-")) {
                    cache = NumberUtil.sub(cache, Optional.ofNullable(dataMap.get(s.substring(1))).orElseGet(() -> 0d));
                    continue;
                }
                cache = NumberUtil.add(cache, Optional.ofNullable(dataMap.get(s)).orElseGet(() -> 0d));
            }
            sumMap.put(key, cache.longValue());
        });
        return sumMap;
    }

    public static String mapDispatchType(Integer dispatchType, Integer secondType) {
        String fineType = null;
        if (DisPatchConstant.DISPATCH_NOT_IN_AREA.equals(dispatchType)) {
            fineType = "2";
        } else if (DisPatchConstant.DISPATCH_NO_IN_PARK.equals(dispatchType)) {
            fineType = "1";
        } else if (DisPatchConstant.DISPATCH_NO_PARK_AREA.equals(dispatchType)){
            //禁停区调度费
            fineType = "5";
        }
        if (DisPatchConstant.DISPATCH_HELMET.equals(secondType)) {
            fineType = fineType == null ? "3" : fineType + ",3";
        }
        return fineType;
    }

    /**
     * 获取时长最近接的一张优惠券
     */
    public static CouponUserDto getTimeCoupon(List<CouponUserDto> coupon, Integer time) {
        CouponUserDto couponUser = null;
        if (!CollectionUtils.isEmpty(coupon)) {
            for (CouponUserDto couponUserDto : coupon) {
                if (time <= couponUserDto.getCouponTime()) {
                    couponUser = couponUserDto;
                } else {
                    /**优惠券最大时间比骑行时间小*/
                    if (couponUser == null) {
                        couponUser = couponUserDto;
                    }
                    break;
                }
            }
        }
        return couponUser;
    }

    /**
     * 骑行时间计费
     */
    public static Double getRide(Double mileage, Integer time, AdAccountFee accountFee, Boolean isRideFee) {
        Double allMoney = 0D;//总金额
        Double baseTimeMoney = 0D;//起步时间费用
        Double timeModey = 0D;//超过起步时间费用
        Double baseMileageMoney = 0D;//起步里程费用
        Double mileageMoney = 0D;//超过起步里程费用
        /**判断是否设置了免费骑行时间(分钟)*/
//		Integer time = rideTime-freeTime;
        /**总里程费用*/
        Double allMilMoney = 0D;
        /**总时间费用*/
        Double allTimeMoney = 0D;
        /********************时间计费**********************/
        /*起步时间费用*/
        if (!isRideFee) {
            if (time > 0) {
                if (accountFee.getBaseTimeFee() > 0D) {
                    baseTimeMoney = (double) accountFee.getBaseTimeFee();
                    allTimeMoney = allTimeMoney + baseTimeMoney;
                }

                if (time > accountFee.getBaseTime()) {
                    if (accountFee.getOverTimeFee() > 0D) {
                        allTimeMoney = getTimeMoney(allTimeMoney, time, accountFee, timeModey);
                    }
                }
            }
        } else {
            if (accountFee.getOverTimeFee() > 0D) {
                allTimeMoney = getTimeMoneyRideOverTime(allTimeMoney, time, accountFee, timeModey);
            } else if (accountFee.getOverTimeFee() < 0D) {
                timeModey = Math.abs((double) accountFee.getOverTimeFee());
                allTimeMoney = allTimeMoney + timeModey;
            }
        }
        allMoney = allMoney + allTimeMoney;

        /********************里程计费**********************/
        /**里程>0**/
        if (mileage > 0) {
            /**起步里程费用>0**/
            if (accountFee.getBaseMileFee() > 0D) {
                baseMileageMoney = (double) accountFee.getBaseMileFee();
                allMilMoney = allMilMoney + baseMileageMoney;
            }
            /**超出部分费用>0**/
            if (mileage > accountFee.getBaseMile()) {
                if (accountFee.getOverMileFee() > 0D) {
                    allMilMoney = getMiMoney(allMilMoney, mileage, accountFee, mileageMoney);
                }
            }
        }
        allMoney = allMoney + allMilMoney;
        return allMoney;
    }

    /**
     * 向上取整
     *
     * @param d
     * @return
     */
    public static double formatDouble(double d) {
        BigDecimal bg = new BigDecimal(d).setScale(0, RoundingMode.UP);
        return bg.doubleValue();
    }

    /**
     * 骑行时间计费
     *
     * @param rideLog
     * @param accountFee
     * @return
     */
    public static Double getRide(RideLog rideLog, AdAccountFee accountFee, Double mileage, Park park, Integer freeTime,
                                 Integer freeDistance,List<CouponUserDto> coupon, CouponUserDto couponUserDB, Boolean isRideFee) {
        Double allMoney = 0D;//总金额
        Double baseTimeMoney = 0D;//起步时间费用
        Double timeModey = 0D;//超过起步时间费用
        Double baseMileageMoney = 0D;//起步里程费用
        Double mileageMoney = 0D;//超过起步里程费用
        Integer time = 0;//骑行时间
        Integer stopTime = 0;//临时停车时长(min)

        /**判断是否免费骑行*/
        Integer freeConditionType = Optional.ofNullable(accountFee.getFreeConditionType()).orElse(0);
        Integer rideTime = DateTimeUtil.getMinDiffer(rideLog.getStartTime());
        //公里转米
        int distance = (int) (mileage * 1000);
        int freeType = MoneyUtil.countFreeType(rideTime, distance, freeTime, freeDistance, freeConditionType);
        if (freeType > 0){
            return 0D;
        }

        /**总里程费用*/
        Double allMilMoney = 0D;
        /**总时间费用*/
        Double allTimeMoney = 0D;

        /********************时间计费******************/
        /**骑行分钟数*/
        time = DateTimeUtil.getMinuteByTime(rideLog.getStartTime(), rideLog.getEndTime(), 1, stopTime);
        /**时间优惠券*/
        CouponUserDto couponUser = null;
        /**取最接近其骑行时长的时间优惠券*/
        if (coupon.size() > 0) {
            for (CouponUserDto couponUserDto : coupon) {
                if (time <= couponUserDto.getCouponTime()) {
                    couponUser = couponUserDto;
                } else {
                    /**优惠券最大时间比骑行时间小*/
                    if (couponUser == null) {
                        couponUser = couponUserDto;
                    }
                    break;
                }
            }
        }

        /**可使用的优惠券不为空*/
        if (couponUser != null) {
            BeanUtils.copyProperties(couponUser, couponUserDB);
            LogUtil.info("使用时间优惠券=" + couponUserDB.toString());
            if (couponUserDB.getCouponTime() >= time) {
                time = 0;
            } else {
                time = time - couponUserDB.getCouponTime();
            }

        }
        if (!isRideFee) {
            /*起步时间费用*/
            if (accountFee.getBaseTimeFee() > 0D && time > 0) {
                baseTimeMoney = (double) accountFee.getBaseTimeFee();
                allTimeMoney = allTimeMoney + baseTimeMoney;
            }

            if (time > accountFee.getBaseTime()) {
                if (accountFee.getOverTimeFee() > 0D) {
                    allTimeMoney = getTimeMoney(allTimeMoney, time, accountFee, timeModey);
                } else if (accountFee.getOverTimeFee() < 0D) {
                    timeModey = Math.abs((double) accountFee.getOverTimeFee());
                    allTimeMoney = allTimeMoney + timeModey;
                }
            }
        } else {
            if (accountFee.getOverTimeFee() > 0D) {
                allTimeMoney = getTimeMoneyRideOverTime(allTimeMoney, time, accountFee, timeModey);
            } else if (accountFee.getOverTimeFee() < 0D) {
                timeModey = Math.abs((double) accountFee.getOverTimeFee());
                allTimeMoney = allTimeMoney + timeModey;
            }
        }

        allMoney = allMoney + allTimeMoney;

        /********************里程计费**********************/
        /*起步里程费用*/
        if (mileage > 0 && accountFee.getBaseMileFee() > 0D) {
            baseMileageMoney = (double) accountFee.getBaseMileFee();
            allMilMoney = allMilMoney + baseMileageMoney;
        }

        /*超出部分费用*/
        if (accountFee.getOverMileFee() > 0D) {
            if (mileage != null && mileage > 0) {
                allMilMoney = getMiMoney(allMilMoney, mileage, accountFee, mileageMoney);
            }
        }
        allMoney = allMoney + allMilMoney;
        return allMoney;
    }


    /**
     * 获取骑行费用
     *
     * @param
     * @return
     */
    public static Double getRideFee(Integer time, Double mileage, AdAccountFee accountFee, Integer freeTime) {
        double allMoney = 0D;//总金额
        double baseTimeMoney = 0D;//起步时间费用
        double timeModey = 0D;//超过起步时间费用
        double baseMileageMoney = 0D;//起步里程费用
        double mileageMoney = 0D;//超过起步里程费用
        //公里转米
        int distance = (int) (mileage * 1000);
        // 公里向上取整
        mileage = Math.ceil(mileage);
        /**判断是否免费骑行*/
        Integer freeConditionType = accountFee.getFreeConditionType();
        Integer freeDistance = accountFee.getFreeDistance();
        int freeType = MoneyUtil.countFreeType(time, distance, freeTime, freeDistance, freeConditionType);
        if (freeType > 0){
            return 0D;
        }

        /**总里程费用*/
        double allMilMoney = 0D;
        /**总时间费用*/
        double allTimeMoney = 0D;
        /*起步时间费用*/
        if (accountFee.getBaseTimeFee() > 0D && time > 0 && accountFee.getBaseTimeFee() > 0) {
            baseTimeMoney = (double) accountFee.getBaseTimeFee();
            allTimeMoney = allTimeMoney + baseTimeMoney;
        }

        if (time > accountFee.getBaseTime()) {
            if (accountFee.getOverTimeFee() > 0D) {
                allTimeMoney = getTimeMoney(allTimeMoney, time, accountFee, timeModey);
            } else if (accountFee.getOverTimeFee() < 0D) {
                timeModey = Math.abs((double) accountFee.getOverTimeFee());
                allTimeMoney = allTimeMoney + timeModey;
            }
        }

        allMoney = allMoney + allTimeMoney;

        /********************里程计费**********************/
        /*起步里程费用*/
        if (mileage > 0 && accountFee.getBaseMileFee() > 0D) {
            baseMileageMoney = (double) accountFee.getBaseMileFee();
            allMilMoney = allMilMoney + baseMileageMoney;
        }

        /*超出部分费用*/
        if (accountFee.getOverMileFee() > 0D) {
            if (mileage != null && mileage > 0) {
                allMilMoney = getMiMoney(allMilMoney, mileage, accountFee, mileageMoney);
            }
        }
        allMoney = allMoney + allMilMoney;

        return allMoney;
    }

    /**
     * 里程收费
     *
     * @param mileage
     * @param accountFee
     * @param mileageMoney
     * @return
     */
    public static double getMiMoney(double allMilMoney, double mileage, AdAccountFee accountFee, double mileageMoney) {
        if (mileage > accountFee.getBaseMile()) {
            int num = (int) (mileage - accountFee.getBaseMile()) / accountFee.getOverMile();
            if ((mileage - accountFee.getBaseMile()) % accountFee.getOverMile() > 0) {
                num = num + 1;
            }
            mileageMoney = DoubleUtil.format((double) accountFee.getOverMileFee() * num);
            allMilMoney = allMilMoney + mileageMoney;
        }
        /**里程封顶金额*/
        //accountFee.getCapMile()>0&&mileage>accountFee.getCapMile()&&
//        if (accountFee.getCapMileFee() > 0 && allMilMoney > accountFee.getCapMileFee()) {
//            /**超出封顶时间继续收费*/
//            if (mileage > accountFee.getCapMile()) {
//                /**查看是否多次达到封顶时长*/
//                Integer count = (int) mileage / accountFee.getCapMile();
//                Integer model = (int) mileage % accountFee.getCapMile();
//                allMilMoney = count * accountFee.getCapMileFee().doubleValue();
//                /**计算超出封顶时间的时长*/
//                Integer num = ((model) / accountFee.getOverMile());
//                if ((model) % accountFee.getOverMile() > 0) {
//                    num = num + 1;
//                }
//                mileageMoney = DoubleUtil.format((double) accountFee.getOverMileFee() * num);
//                /**未达到封顶需要看费用是否达到了封顶费用*/
//                if (mileageMoney > accountFee.getCapMileFee()) {
//                    mileageMoney = accountFee.getCapMileFee();
//                }
//                allMilMoney = allMilMoney + mileageMoney;
//            } else {
//                allMilMoney = (double) accountFee.getCapMileFee();
//            }
//        }
        allMilMoney = getCapMileFeeNew((int) allMilMoney,(int) mileage,accountFee);

        return allMilMoney;
    }

    /**
     * 时长收费
     *
     * @param time
     * @param accountFee
     * @param timeModey
     * @return
     */
    public static double getTimeMoney(double allTimeMoney, Integer time, AdAccountFee accountFee, double timeModey) {

        /*骑行时间大于起步时间*/
        if ((time - accountFee.getBaseTime()) > 0) {
            int num = (time - accountFee.getBaseTime()) / accountFee.getOverTime();
            if ((time - accountFee.getBaseTime()) % accountFee.getOverTime() > 0) {
                num = num + 1;
            }
            timeModey = DoubleUtil.format((double) accountFee.getOverTimeFee() * num);
            allTimeMoney = allTimeMoney + timeModey;
        }
        /**时间封顶金额*/
        /*if(accountFee.getCapTimeFee()>0&&allTimeMoney>accountFee.getCapTimeFee()){
         *//**超出封顶时间继续收费*//*
			if(time>accountFee.getCapTime()){
				*//**查看是否多次达到封顶时长*//*
				Integer count  = time/accountFee.getCapTime();
				Integer model = time%accountFee.getCapTime();
				*//**超出达到count个封顶金额*//*
				allTimeMoney=count*accountFee.getCapTimeFee().doubleValue();
				*//**计算超出封顶时间的时长*//*
				Integer num =(model)/accountFee.getOverTime();
				if((model)%accountFee.getOverTime()>0){
					num=num+1;
				}
				timeModey=DoubleUtil.format((double)accountFee.getOverTimeFee()*num);
				*//**未达到封顶时长需要看费用是否达到了封顶费用*//*
				if(timeModey>accountFee.getCapTimeFee()){
					timeModey=accountFee.getCapTimeFee();
				}
				allTimeMoney=allTimeMoney+timeModey;
			}else{
				allTimeMoney=(double)accountFee.getCapTimeFee();
			}
		}*/
        allTimeMoney = getCapTimeFeeNew((int) allTimeMoney, time, accountFee);
        return allTimeMoney;
    }

    private static double getTimeMoneyRideOverTime(double allTimeMoney, Integer time,
                                                   AdAccountFee accountFee, double timeModey) {
        /*骑行时间大于起步时间*/
        Integer num = time / accountFee.getOverTime();
        if (time % accountFee.getOverTime() > 0) {
            num = num + 1;
        }
        timeModey = DoubleUtil.format((double) accountFee.getOverTimeFee() * num);
        allTimeMoney = allTimeMoney + timeModey;

        allTimeMoney = getCapTimeFeeNew((int) allTimeMoney, time, accountFee);
        return allTimeMoney;
    }


    /**
     * 封顶计费
     *
     * @param allTimeMoney
     * @param time
     * @param accountFee
     * @param timeModey
     * @return
     */
    public static double getCapTimeFee(double allTimeMoney, Integer time, AdAccountFee accountFee, double timeModey) {
        /**时间封顶金额*/
        if (accountFee.getCapTimeFee() > 0 && allTimeMoney > accountFee.getCapTimeFee()) {
            /**超出封顶时间继续收费*/
            if (time > accountFee.getCapTime()) {
                /**查看是否多次达到封顶时长*/
                Integer count = time / accountFee.getCapTime();
                Integer model = time % accountFee.getCapTime();
                /**超出达到count个封顶金额*/
                allTimeMoney = count * accountFee.getCapTimeFee().doubleValue();
                /**计算超出封顶时间的时长*/
                Integer num1 = (model) / accountFee.getOverTime();
                if ((model) % accountFee.getOverTime() > 0) {
                    num1 = num1 + 1;
                }
                timeModey = DoubleUtil.format((double) accountFee.getOverTimeFee() * num1);
                /**未达到封顶时长需要看费用是否达到了封顶费用*/
                if (timeModey > accountFee.getCapTimeFee()) {
                    timeModey = accountFee.getCapTimeFee();
                }
                allTimeMoney = allTimeMoney + timeModey;
            } else {
                allTimeMoney = (double) accountFee.getCapTimeFee();
            }
        }
        return allTimeMoney;
    }



    /**
     * 封顶计费
     *
     * @param allTimeMoney
     * @param time
     * @param accountFee
     * @return
     */
    public static Integer getCapTimeFeeNew(Integer allTimeMoney, Integer time, AdAccountFee accountFee) {
        /**时间封顶金额  启用*/
        if (accountFee.getCapTime() > 0 && accountFee.getCapTimeFee() > 0) {
            // 在一个封顶时间周期内
            if (time <= accountFee.getCapTime()){
                return allTimeMoney < accountFee.getCapTimeFee() ? allTimeMoney : accountFee.getCapTimeFee();
            }
            // 骑行时间超过一个封顶时间周期
            int count = 0;
            count = time / accountFee.getCapTime();
            if ((time % accountFee.getCapTime()) > 0){
                count = count + 1;
            }
            // 封顶计费总金额
            int capAllMoney = 0;
            // 当前封顶计费周期内的费用
            int perCapMoney = 0;
            // 计数器
            int num = 0;
            for (int i = 0; i < count; i++){
                perCapMoney = 0;
                // 第一个封顶时间周期，考虑起步价
                if (i == 0){
                    perCapMoney += accountFee.getBaseTimeFee();
                    // 封顶计费时间 小于 起步时间的时候会出现问题
                    num = countPeriodTime(accountFee.getCapTime() - accountFee.getBaseTime(),accountFee);
                } else if (i == count-1){   // 最后一个封顶时间周期
                    num = countPeriodTime(time-i*accountFee.getCapTime(),accountFee);
                }else { //  中间的都是完整的封顶时间周期
                    num = countPeriodTime(accountFee.getCapTime(), accountFee);
                }
                // 计算周期内的费用，和封顶计费取小者
                perCapMoney += accountFee.getOverTimeFee() * num;
                if (perCapMoney > accountFee.getCapTimeFee()){
                    perCapMoney = accountFee.getCapTimeFee();
                }
                capAllMoney += perCapMoney;
            }
            return capAllMoney;
        }
        return allTimeMoney;
    }

    public static Integer getCapMileFeeNew(Integer allMileMoney, Integer mile, AdAccountFee accountFee) {
        /**时间封顶金额  启用*/
        if (accountFee.getCapMile() > 0 && accountFee.getCapMileFee() > 0) {
            // 在一个封顶时间周期内
            if (mile <= accountFee.getCapMile()){
                return allMileMoney < accountFee.getCapMileFee() ? allMileMoney : accountFee.getCapMileFee();
            }
            // 骑行时间超过一个封顶时间周期
            int count = 0;
            count = mile / accountFee.getCapMile();
            if ((mile % accountFee.getCapMile()) > 0){
                count = count + 1;
            }
            // 封顶计费总金额
            int capAllMoney = 0;
            // 当前封顶计费周期内的费用
            int perCapMoney = 0;
            // 计数器
            int num = 0;
            for (int i = 0; i < count; i++){
                perCapMoney = 0;
                // 第一个封顶时间周期，考虑起步价
                if (i == 0){
                    perCapMoney += accountFee.getBaseMileFee();
                    // 封顶计费时间 小于 起步时间的时候会出现问题
                    num = countPeriodMile(accountFee.getCapMile() - accountFee.getBaseMile(),accountFee);
                } else if (i == count-1){   // 最后一个封顶时间周期
                    num = countPeriodMile(mile-i*accountFee.getCapMile(),accountFee);
                }else { //  中间的都是完整的封顶时间周期
                    num = countPeriodMile(accountFee.getCapMile(), accountFee);
                }
                // 计算周期内的费用，和封顶计费取小者
                perCapMoney += accountFee.getOverTimeFee() * num;
                if (perCapMoney > accountFee.getCapMileFee()){
                    perCapMoney = accountFee.getCapMileFee();
                }
                capAllMoney += perCapMoney;
            }
            return capAllMoney;
        }
        return allMileMoney;
    }

    /**
     * 计算封顶计费周期内的正常计费周期个数
     * @param resTime
     * @param accountFee
     * @return
     */
    private static int countPeriodTime(int resTime, AdAccountFee accountFee){
        int num = resTime / accountFee.getOverTime();
        if (resTime % accountFee.getOverTime() > 0){
            num = num + 1;
        }
        return num;
    }

    /**
     * 计算封顶计费周期内的正常计费周期个数
     * @param resMile
     * @param accountFee
     * @return
     */
    private static int countPeriodMile(int resMile, AdAccountFee accountFee){
        int num = resMile / accountFee.getOverMile();
        if (resMile % accountFee.getOverTime() > 0){
            num = num + 1;
        }
        return num;
    }

    /**
     * 计算免费骑行类型
     *
     * @param rideTime 骑行时间
     * @param rideDistance 骑行里程
     * @param freeRideTime 免费骑行时间
     * @param freeRideDistance 免费骑行里程
     * @param freeConditionType 骑行条件类型
     * @return 免费骑行类型 -1:不满足免费 1:免费时长骑行，2：满足免费规则全部启用条件骑行，3：满足免费规则任一启用条件骑行
     */
    public static int countFreeType(int rideTime, int rideDistance, int freeRideTime, Integer freeRideDistance, Integer freeConditionType){
        freeRideDistance = freeRideDistance == null ? 0 : freeRideDistance;
        freeConditionType = freeConditionType == null ? 0 : freeConditionType;
        if (freeRideDistance == 0){
            if (rideTime <= freeRideTime) {
                return AdAccountFeeConstant.FREE_RIDE_TYPE_FREE_TIME;
            }
        }else if(freeRideTime == 0){
            if (rideDistance <= freeRideDistance) {
                return AdAccountFeeConstant.FREE_RIDE_TYPE_FREE_DISTANCE;
            }
        } else{
            if (AdAccountFeeConstant.FREE_CONDITION_TYPE_ALL == freeConditionType){
                if (rideTime <= freeRideTime && rideDistance <= freeRideDistance) {
                    return AdAccountFeeConstant.FREE_RIDE_TYPE_FREE_CONDITION_ALL;
                }
            }
            if (AdAccountFeeConstant.FREE_CONDITION_TYPE_OR == freeConditionType){
                if (rideTime <= freeRideTime || rideDistance <= freeRideDistance) {
                    return AdAccountFeeConstant.FREE_RIDE_TYPE_FREE_CONDITION_OR;
                }
            }
        }
        return AdAccountFeeConstant.FREE_RIDE_TYPE_NOT_FREE;
    }

    public static void main(String[] args) {
        AdAccountFee adAccountFee = new AdAccountFee();
        adAccountFee.setBaseTime(1);
        adAccountFee.setBaseTimeFee(1);
        adAccountFee.setOverTime(1);
        adAccountFee.setOverTimeFee(2);
        adAccountFee.setCapTime(30);
        adAccountFee.setCapTimeFee(100);
        adAccountFee.setBaseMile(1);
        adAccountFee.setBaseMileFee(1);
        adAccountFee.setOverMile(1);
        adAccountFee.setOverMileFee(2);
        adAccountFee.setCapMile(30);
        adAccountFee.setCapMileFee(100);

        Double rideFee = getRideFee(60, 60D, adAccountFee, 0);
        System.out.println(rideFee);
        System.out.println(Math.ceil(60.001));
    }


}
